// 面单打印 指令集
import {
	TextEncoder,
	TextDecoder
} from '@/utils/text-encoding';

/** 创建面单打印机 */
export function createGprinter() {
	// 创建实例并挂载
	const instance = new Object();
	instance.name = "面单打印机";

	// 打印指令数据集
	let commandArray = [];
	// 需要特别注意，在每一条指令结尾需要加入换行符，即字符串“\r\n”或 16进制 0x0D 0x0A
	const newlineString = '\r\n';
	// const newlineHexadecimal = '0x0D 0x0A';

	/** 挂载方法：创建新的打印对象 标签初始化指令
	 * 指令语法 <!> {offset} <200> <200> {height} {qty}
	 * <!> 使用“!”作为控制会话的起始字符 
	 * {offset} 标签横向偏移量
	 * <200> 横向 DPI
	 * <200> 纵向 DPI
	 * {height} 标签最大高度
	 * @param height 标签最大高度
	 * @param offset 标签横向偏移量
	 * @param qty 标签数量
	 */
	instance.createNew = function(height = 210, offset = 0, qty = 1) {
		commandArray = [];
		const data = `! ${offset} 200 200 ${height} ${qty}`;
		instance.addCommand(data);
		return instance;
	};

	/** 挂载方法：将指令转成数组后装入打印指令数据集
	 * @param content 指令字符串
	 * @param newline 是否换行
	 */
	instance.addCommand = function(content, newline = true) {
		if (newline === true && content.endsWith(newlineString) === false) {
			content = `${content}${newlineString}`;
		}
		const code = new TextEncoder(
			'gb18030', {
				NONSTANDARD_allowLegacyEncoding: true
			}).encode(content)
		for (let i = 0; i < code.length; ++i) {
			commandArray.push(code[i]);
		}
	};
	/** 挂载方法：获取打印指令数据集
	 */
	instance.getCommand = function() {
		return commandArray;
	};

	/** 挂载方法：启动文件打印
	 * PRINT
	 */
	instance.print = function() {
		const data = `PRINT`;
		instance.addCommand(data);
	};

	/** 挂载方法：横向打印文本
	 * TEXT(或 T) {font} {size} {x} {y} {data}
	 * @param content 字符串内容
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 * @param font 字体名称/编号
				   0	12*24	24*24 简体中文 GB18030
				   1	9*17	24*24 简体中文 GB18030
				   2	12*24	24*24 简体中文 GB18030
				   3	10*20	20*20 简体中文 GBK
				   4	16*32	32*32 简体中文 GBK
				   5	9*17	24*24 简体中文 GB18030
				   6	12*24 
				   7	12*24	24*24 简体中文 GB18030
				   8	12*24	24*24 简体中文 GB18030
				   10	24*48	48*48 简体中文 GBK
				   11	8*16	24*24 简体中文 GB18030
				   13	12*24	24*24 繁体中文 BIG5
				   20	8*16	16*16 简体中文 GB18030
				   24	12*24	24*24 简体中文 GB18030
				   41	8*12
				   42	12*20
				   43	16*24
				   44	24*32
				   45	32*48
				   46	14*19
				   47	21*27
				   48	14*25
				   49	28*56
				   55	8*16	16*16 简体中文 GB18030
	 * @param size 忽略该参数，请输入任意数字
	 */
	instance.text = function(content, x = 0, y = 0, font = 0, size = 0) {
		// const data = `T ${font} ${size} ${x} ${y} ${content}`;
		const data = `TEXT ${font} ${size} ${x} ${y} ${content}`;
		instance.addCommand(data);
	};

	/** 挂载方法：逆时针旋转 90 度，纵向打印文本
	 * VTEXT(或 VT) {font} {size} {x} {y} {data}
	 * TEXT90(或 T90) {font} {size} {x} {y} {data}
	 * @param content 字符串内容
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 * @param font 字体名称/编号
				   0	12*24	24*24 简体中文 GB18030
				   1	9*17	24*24 简体中文 GB18030
				   2	12*24	24*24 简体中文 GB18030
				   3	10*20	20*20 简体中文 GBK
				   4	16*32	32*32 简体中文 GBK
				   5	9*17	24*24 简体中文 GB18030
				   6	12*24 
				   7	12*24	24*24 简体中文 GB18030
				   8	12*24	24*24 简体中文 GB18030
				   10	24*48	48*48 简体中文 GBK
				   11	8*16	24*24 简体中文 GB18030
				   13	12*24	24*24 繁体中文 BIG5
				   20	8*16	16*16 简体中文 GB18030
				   24	12*24	24*24 简体中文 GB18030
				   41	8*12
				   42	12*20
				   43	16*24
				   44	24*32
				   45	32*48
				   46	14*19
				   47	21*27
				   48	14*25
				   49	28*56
				   55	8*16	16*16 简体中文 GB18030
	 * @param size 忽略该参数，请输入任意数字
	 */
	instance.text90 = function(content, x = 0, y = 0, font = 0, size = 0) {
		// const data = `VT ${font} ${size} ${x} ${y} ${content}`;
		// const data = `VTEXT ${font} ${size} ${x} ${y} ${content}`;
		// const data = `T90 ${font} ${size} ${x} ${y} ${content}`;
		const data = `TEXT90 ${font} ${size} ${x} ${y} ${content}`;
		instance.addCommand(data);
	};

	/** 挂载方法：逆时针旋转 80 度，反转打印文本
	 * TEXT180(或 T180) {font} {size} {x} {y} {data}
	 * @param content 字符串内容
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 * @param font 字体名称/编号
				   0	12*24	24*24 简体中文 GB18030
				   1	9*17	24*24 简体中文 GB18030
				   2	12*24	24*24 简体中文 GB18030
				   3	10*20	20*20 简体中文 GBK
				   4	16*32	32*32 简体中文 GBK
				   5	9*17	24*24 简体中文 GB18030
				   6	12*24 
				   7	12*24	24*24 简体中文 GB18030
				   8	12*24	24*24 简体中文 GB18030
				   10	24*48	48*48 简体中文 GBK
				   11	8*16	24*24 简体中文 GB18030
				   13	12*24	24*24 繁体中文 BIG5
				   20	8*16	16*16 简体中文 GB18030
				   24	12*24	24*24 简体中文 GB18030
				   41	8*12
				   42	12*20
				   43	16*24
				   44	24*32
				   45	32*48
				   46	14*19
				   47	21*27
				   48	14*25
				   49	28*56
				   55	8*16	16*16 简体中文 GB18030
	 * @param size 忽略该参数，请输入任意数字
	 */
	instance.text180 = function(content, x = 0, y = 0, font = 0, size = 0) {
		// const data = `T180 ${font} ${size} ${x} ${y} ${content}`;
		const data = `TEXT180 ${font} ${size} ${x} ${y} ${content}`;
		instance.addCommand(data);
	};

	/** 挂载方法：逆时针旋转 270 度，纵向打印文本
	 * TEXT270(或 T270) {font} {size} {x} {y} {data}
	 * @param content 字符串内容
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 * @param font 字体名称/编号
				   0	12*24	24*24 简体中文 GB18030
				   1	9*17	24*24 简体中文 GB18030
				   2	12*24	24*24 简体中文 GB18030
				   3	10*20	20*20 简体中文 GBK
				   4	16*32	32*32 简体中文 GBK
				   5	9*17	24*24 简体中文 GB18030
				   6	12*24 
				   7	12*24	24*24 简体中文 GB18030
				   8	12*24	24*24 简体中文 GB18030
				   10	24*48	48*48 简体中文 GBK
				   11	8*16	24*24 简体中文 GB18030
				   13	12*24	24*24 繁体中文 BIG5
				   20	8*16	16*16 简体中文 GB18030
				   24	12*24	24*24 简体中文 GB18030
				   41	8*12
				   42	12*20
				   43	16*24
				   44	24*32
				   45	32*48
				   46	14*19
				   47	21*27
				   48	14*25
				   49	28*56
				   55	8*16	16*16 简体中文 GB18030
	 * @param size 忽略该参数，请输入任意数字
	 */
	instance.text270 = function(content, x = 0, y = 0, font = 0, size = 0) {
		// const data = `VT ${font} ${size} ${x} ${y} ${content}`;
		// const data = `VTEXT ${font} ${size} ${x} ${y} ${content}`;
		// const data = `T270 ${font} ${size} ${x} ${y} ${content}`;
		const data = `TEXT270 ${font} ${size} ${x} ${y} ${content}`;
		instance.addCommand(data);
	};

	/** 挂载方法：开启横向文本串联
	 * CONCAT {x} {y}
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 */
	instance.concat = function(x = 0, y = 0) {
		const data = `CONCAT ${x} ${y}`;
		instance.addCommand(data);
	};

	/** 挂载方法：打印横向串联文本
	 * {font} {size} {offset} {data}
	 * @param content 字符串内容
	 * @param offset 文本相对起始位置的偏置单位值
	 * @param font 字体名称/编号
				   0	12*24	24*24 简体中文 GB18030
				   1	9*17	24*24 简体中文 GB18030
				   2	12*24	24*24 简体中文 GB18030
				   3	10*20	20*20 简体中文 GBK
				   4	16*32	32*32 简体中文 GBK
				   5	9*17	24*24 简体中文 GB18030
				   6	12*24 
				   7	12*24	24*24 简体中文 GB18030
				   8	12*24	24*24 简体中文 GB18030
				   10	24*48	48*48 简体中文 GBK
				   11	8*16	24*24 简体中文 GB18030
				   13	12*24	24*24 繁体中文 BIG5
				   20	8*16	16*16 简体中文 GB18030
				   24	12*24	24*24 简体中文 GB18030
				   41	8*12
				   42	12*20
				   43	16*24
				   44	24*32
				   45	32*48
				   46	14*19
				   47	21*27
				   48	14*25
				   49	28*56
				   55	8*16	16*16 简体中文 GB18030
	 * @param size 忽略该参数，请输入任意数字
	 */
	instance.concatText = function(content, offset = 0, font = 0, size = 0) {
		const data = `${font} ${size} ${offset} ${content}`;
		instance.addCommand(data);
	};

	/** 挂载方法：终止横向文本串联
	 * CONCAT
	 */
	instance.endConcat = function() {
		const data = `ENDCONCAT`;
		instance.addCommand(data);
	};

	/** 挂载方法：常驻字体放大指定的放大倍数
	 * SETMAG {w} {h}
	 * @param width w 宽度放大倍数，有效放大倍数为 1 到 16
	 * @param height h 高度放大倍数，有效放大倍数为 1 到 16
	 */
	instance.setmag = function(width = 0, height = 0) {
		const data = `SETMAG ${width} ${height}`;
		instance.addCommand(data);
	};

	/** 挂载方法：常驻字体加粗
	 * SETBLOD {value}
	 * @param value 0，不加粗、1，加粗
	 */
	instance.setblod = function(value = 0) {
		const data = `SETBLOD ${value}`;
		instance.addCommand(data);
	};

	/** 挂载方法：横向打印条码
	 * BARCODE(或 B) {type} {width} {ratio} {height} {x} {y} {data}
	 * @param content 条码内容
	 * @param width 窄条的单位宽度
	 * @param height 条码的单位高度
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 * @param type 条码种类
	 * 			   UPCA          UPC-A
	 * 			   UPCE          UPC-E
	 * 			   EAN13         EAN/JAN-13
	 * 			   EAN8          EAN/JAN-8
	 * 			   39            Code39
	 * 			   93            Code93/Ext.93
	 * 			   128           Code128
	 * 			   CODABAR       Codabar
	 * @param ratio 宽条与窄条的比率
	 * 			    0 1.5:1
	 * 			    1 2.0:1
	 * 			    2 2.5:1
	 * 			    3 3.0:1
	 * 			    4 3.5:1
	 * 			    20 2.0:1
	 * 			    21 2.1:1
	 * 			    22 2.2:1
	 * 			    23 2.3:1
	 * 			    24 2.4:1
	 * 			    25 2.5:1
	 * 			    26 2.6:1
	 * 			    27 2.7:1
	 * 			    28 2.8:1
	 * 			    29 2.9:1
	 * 			    30 3.0:1
	 */
	instance.barCode = function(content, width = 1, height = 50, x = 0, y = 0, type = 128, ratio = 1) {
		// const data = `B ${type} ${width} ${ratio} ${height} ${x} ${y} ${content}`;
		const data = `BARCODE ${type} ${width} ${ratio} ${height} ${x} ${y} ${content}`;
		instance.addCommand(data);
	};

	/** 挂载方法：纵向打印条码
	 * VBARCODE(或 VB) {type} {width} {ratio} {height} {x} {y} {data}
	 * @param content 条码内容
	 * @param width 窄条的单位宽度
	 * @param height 条码的单位高度
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 * @param type 条码种类
	 * 			   UPCA          UPC-A
	 * 			   UPCE          UPC-E
	 * 			   EAN13         EAN/JAN-13
	 * 			   EAN8          EAN/JAN-8
	 * 			   39            Code39
	 * 			   93            Code93/Ext.93
	 * 			   128           Code128
	 * 			   CODABAR       Codabar
	 * @param ratio 宽条与窄条的比率
	 * 			    0 1.5:1
	 * 			    1 2.0:1
	 * 			    2 2.5:1
	 * 			    3 3.0:1
	 * 			    4 3.5:1
	 * 			    20 2.0:1
	 * 			    21 2.1:1
	 * 			    22 2.2:1
	 * 			    23 2.3:1
	 * 			    24 2.4:1
	 * 			    25 2.5:1
	 * 			    26 2.6:1
	 * 			    27 2.7:1
	 * 			    28 2.8:1
	 * 			    29 2.9:1
	 * 			    30 3.0:1
	 */
	instance.barCodeV = function(content, width = 1, height = 50, x = 0, y = 0, type = 128, ratio = 1) {
		// const data = `VB ${type} ${width} ${ratio} ${height} ${x} ${y} ${content}`;
		const data = `VBARCODE ${type} ${width} ${ratio} ${height} ${x} ${y} ${content}`;
		instance.addCommand(data);
	};

	/** 挂载方法：通过创建条码时所用的相同数据来标记条码
	 * BARCODE-TEXT(或 BT) {font number} {font size} {offset}
	 * 注：使用 BARCODE-TEXT OFF(或 BT OFF)可以禁用它
	 * @param font_number 注释条码时要使用的字体号
	 * @param offset 窄条的单位宽度
	 * @param font_size 文本距离条码的单位偏移量
	 */
	instance.barCodeText = function(font_number, offset = 1, font_size = 0) {
		// const data = `BT ${type} ${font_number} ${font_size} ${offset}`;
		const data = `BARCODE-TEXT ${font_number} ${font_size} ${offset}`;
		instance.addCommand(data);
	};

	/** 挂载方法：禁用创建条码时所用的相同数据来标记条码
	 * BARCODE-TEXT OFF(或 BT OFF)
	 */
	instance.barCodeTextOff = function() {
		// const data = `BT OFF}`;
		const data = `BARCODE-TEXT OFF`;
		instance.addCommand(data);
	};


	/** 挂载方法：横向打印二维码
	 * BARCODE(或 B) QR {x} {y} [M n] [U n] {data} ENDQR
	 * @param content 二维码内容：<纠错等级><掩码><输入模式>,<所需生成二维码的数据>
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 * @param m QR Code 规范编号,1 或 2，推荐为 2
	 * @param u 模块的单位宽度/单位高度 1-32，默认为 6
	 */
	instance.qrCode = function(content, x = 0, y = 0, m = 2, u = 6) {
		// const data = `B QR ${x} ${y} ${m} ${u} ${content}${newlineString}ENDQR`;
		const data = `BARCODE QR ${x} ${y} ${m} ${u} ${content}${newlineString}ENDQR`;
		instance.addCommand(data);
	};

	/** 挂载方法：纵向打印二维码
	 * VBARCODE(或 VB) QR {x} {y} [M n] [U n] {data} ENDQR
	 * @param content 二维码内容：<纠错等级><掩码><输入模式>,<所需生成二维码的数据>
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 * @param m QR Code 规范编号,1 或 2，推荐为 2
	 * @param u 模块的单位宽度/单位高度 1-32，默认为 6
	 */
	instance.qrCodeV = function(content, x = 0, y = 0, m = 2, u = 6) {
		// const data = `VB QR ${x} ${y} ${m} ${u} ${content}${newlineString}ENDQR`;
		const data = `VBARCODE QR ${x} ${y} ${m} ${u} ${content}${newlineString}ENDQR`;
		instance.addCommand(data);
	};

	/**************************************图形指令**************************************/

	/** 挂载方法：生成具有指定线条宽度的矩形
	 * BOX {x0} {y0} {x1} {y1} {width}
	 * @param x0 左上角的 X 坐标
	 * @param y0 左上角的 Y 坐标
	 * @param x1 右下角的 X 坐标
	 * @param y1 右下角的 Y 坐标
	 * @param width 形成矩形框的线条的单位宽度
	 */
	instance.box = function(x0, y0, x1, y1, width = 1) {
		const data = `BOX ${x0} ${y0} ${x1} ${y1} ${width}`;
		instance.addCommand(data);
	};

	/** 挂载方法：绘制指定长度、宽度和角度方向的线条
	 * LINE {x0} {y0} {x1} {y1} {width}
	 * @param x0 起始点的 X 坐标
	 * @param y0 起始点的 Y 坐标
	 * @param x1 终止点的 X 坐标
	 * @param y1 终止点的 Y 坐标
	 * @param width 线条的单位宽度
	 */
	instance.line = function(x0, y0, x1, y1, width = 1) {
		const data = `LINE ${x0} ${y0} ${x1} ${y1} ${width}`;
		instance.addCommand(data);
	};

	/** 挂载方法：绘制指定长度、宽度和角度方向的反色线条
	 * INVERSE-LINE (或 IL) {x0} {y0} {x1} {y1} {width}
	 * @param x0 起始点的 X 坐标
	 * @param y0 起始点的 Y 坐标
	 * @param x1 终止点的 X 坐标
	 * @param y1 终止点的 Y 坐标
	 * @param width 反色线条的单位宽度
	 */
	instance.inverseLine = function(x0, y0, x1, y1, width = 1) {
		// const data = `IL ${x0} ${y0} ${x1} ${y1} ${width}`;
		const data = `INVERSE-LINE ${x0} ${y0} ${x1} ${y1} ${width}`;
		instance.addCommand(data);
	};

	/** 挂载方法：横向打印扩展图形
	 * EXPANDED-GRAPHICS(或 EG) {width} {height} {x} {y} {data}
	 * @param content 图形数据，由上至下，由左至右
	 * @param width 图像的宽度(以字节为单位)
	 * @param height 图像的高度(以点为单位)
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 */
	instance.expandedGraphics = function(content, width, height, x = 0, y = 0) {
		// const data = `EG ${width} ${height} ${x} ${y} ${content}`;
		const data = `EXPANDED-GRAPHICS ${width} ${height} ${x} ${y} ${content}`;
		instance.addCommand(data);
	};

	/** 挂载方法：横向打印压缩图形
	 * COMPRESSED-GRAPHICS(或 CG) {width} {height} {x} {y} {data}
	 * @param content 图形数据，由上至下，由左至右
	 * @param width 图像的宽度(以字节为单位)
	 * @param height 图像的高度(以点为单位)
	 * @param x 横向起始位置
	 * @param y 纵向起始位置
	 */
	instance.compressedGraphics = function(content, width, height, x = 0, y = 0) {
		// const data = `CG ${width} ${height} ${x} ${y} ${content}`;
		const data = `COMPRESSED-GRAPHICS ${width} ${height} ${x} ${y} ${content}`;
		instance.addCommand(data);
	};

	/**************************************高级指令**************************************/

	/** 挂载方法：对齐方式
	 * {command} [end]
	 * @param command CENTER: 居中对齐所有后续字段、LEFT: 左对齐所有后续字段、RIGHT: 右对齐所有后续字段
	 * @param end 纵向起始位置
	 */
	instance.justification = function(command = 'LEFT', end = null) {
		let data = '';
		if (end) {
			data = `${command}`;
		} else {
			data = `${command} ${end}`;
		}
		instance.addCommand(data);
	};

	/** 挂载方法：设定页面宽度为打印机的完整宽度
	 * PAGE-WIDTH(或 PW) {width}
	 * @param width 页面的单位宽度
	 */
	instance.pageWidth = function(width) {
		// const data = `PW ${width}`;
		const data = `PAGE-WIDTH ${width}`;
		instance.addCommand(data);
	};

	/** 挂载方法：设置电机的最高速度级别
	 * SPEED {speed level}
	 * @param speed_level 0-5
	 */
	instance.speed = function(speed_level = 1) {
		const data = `SPEED ${speed_level}`;
		instance.addCommand(data);
	};

	/** 挂载方法：指示打印机让蜂鸣器发出给定时间长度的声音
	 * BEEP {beep_length}
	 * @param beep_length 蜂鸣持续时间，以 1/8 秒为单位递增
	 */
	instance.beep = function(beep_length = 1) {
		const data = `BEEP ${beep_length}`;
		instance.addCommand(data);
	};

	/**************************************返回实例**************************************/
	return instance;
}

/** 面单打印机 */
const gprinterClient = createGprinter();

export default gprinterClient;
